package com.caltco.cargo.ops.modules.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.caltco.cargo.ops.auth.bo.AdminUserDetails;
import com.caltco.cargo.ops.common.base.gen.BaseServiceImpl;
import com.caltco.cargo.ops.modules.sys.dao.CommentsDao;
import com.caltco.cargo.ops.modules.sys.entity.Comments;
import com.caltco.cargo.ops.modules.sys.entity.SysUserEntity;
import com.caltco.cargo.ops.modules.sys.request.CommentsRequest;
import com.caltco.cargo.ops.modules.sys.service.CommentsService;
import com.caltco.cargo.ops.modules.sys.vo.CommentsVO;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class CommentsServiceImp extends BaseServiceImpl<CommentsDao, Comments> implements CommentsService {

    private final CommentsDao commentsDao;

    public CommentsServiceImp(CommentsDao commentsDao) {
        this.commentsDao = commentsDao;
    }

    public Long getUserIdByToken() {
        return ((AdminUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUserEntity().getUserId();
    }

    @Override
    public Boolean addComment(CommentsRequest request) {

        Long UserId = getUserIdByToken();
        request.setUserId(UserId);  // 补充属性，所以前端请求的时候不需要携带这个数据

        // 判断添加的是顶级评论还是子评论（这里其实没太大必要，我是想着后面有功能点可能要用到这个状态，就设置了）
        // 【注意】这里解释一下为什么是等于0不是等于null。因为前面说过bigint自动映射为long了，long类型没有值则是为0
        if ( request.getRootCommentId() == null && request.getParentId() == null) {    // 顶级评论
            // 设置业务状态 1 评论 2 回复
            request.setStatus(1);
        } else {  // 子评论/回复
            request.setStatus(2);
        }

        Comments comments = new Comments();
        BeanUtil.copyProperties(request, comments);

        return this.save(comments);
    }

    @Override
    public List<CommentsVO> getCommentListByMomentId(CommentsRequest request) {

//        // 1.创建PageBean对象
//        PageBean<CommentsVO> pb = new PageBean<>();
//
//        // 2.开启分页查询 PageHelper
//        PageHelper.startPage(commentsPageQueryDTO.getPageNum(), commentsPageQueryDTO.getPageSize());
//
//        // 3.查所有的根评论
////        List<CommentsVO> commentsVOList = commentMapper.getAllRoot(commentsPageQueryDTO);
        List<CommentsVO> commentsVOS = commentsDao.selectJoinList(CommentsVO.class, new MPJLambdaWrapper<Comments>()
                        .selectAll(Comments.class)
                        .selectAs(SysUserEntity::getUserPhoto, CommentsVO::getAvatar)
                        .leftJoin(SysUserEntity.class, SysUserEntity::getId, Comments::getUserId)
                        .eq(Comments::getTaskId, request.getTaskId())
                        .eq(Comments::getStatus, 1)
                        .eq(Comments::getParentId, request.getParentId())
                        .eq(Comments::getRootCommentId, 0));
        // 4.遍历commentsVOList列表，添加对应的子评论（二级评论在一级评论的children字段中，三级评论在二级评论的children字段中，以此类推）
        for (CommentsVO comment : commentsVOS) {
            // 调用查询子评论的方法，需要该顶级评论自己的 id 与 关联主体 id
            // 【注意】这里就用到了vo中最后一个子评论列表 private List<CommentsVO> children 字段，设置子孩子的时候也是按照CommentsVO类型来返回数据的
            comment.setChildren(getChildrenComments(comment.getId(), request.getTaskId()));
        }

        return commentsVOS;
    }


    private List<CommentsVO> getChildrenComments(long parentId, long taskId) {

        // 查所有的子评论（需要的是该子评论的直接父评论ID，一开始从二级评论开始查，也就是调用此方法时传进来的顶级评论id[这就是二级评论的直接父评论ID]；还有关联主体id）
//        List<Comments> commentsVOList = commentMapper.getChildren(parentId, momentId);

        List<CommentsVO> commentsVOS = commentsDao.selectJoinList(CommentsVO.class, new MPJLambdaWrapper<Comments>()
                .leftJoin(SysUserEntity.class, SysUserEntity::getId, Comments::getUserId)
                .selectAll(Comments.class)
                .selectAs(SysUserEntity::getUserPhoto, CommentsVO::getAvatar)
                .select(SysUserEntity::getUsername)
                .eq(Comments::getParentId, parentId)
                .eq(Comments::getTaskId, taskId)
                .eq(Comments::getStatus, 2));
        // 遍历名为commentsVOList的CommentsVO类型的集合
        for (CommentsVO comment : commentsVOS) {
            // 此处用到了递归，递归查询每一级评论，每次调用本层的id去查子一层
            // 【注意】每一个子孩子还有子孩子的话，也是按照CommentsVO类型来存放
            comment.setChildren(getChildrenComments(comment.getId(), taskId));
        }

        return commentsVOS;
    }
}
